package com.tensquare.manager.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import util.JwtUtil;

import javax.servlet.http.HttpServletRequest;

@Component
public class ManagerFilter extends ZuulFilter {

    @Autowired
    private JwtUtil jwtUtil;

    //1.过滤器类型：pre：代表在执行网关路由前被调用  post：代表在执行route（路由）和error(处理请求发生错误时执行)之间执行。
    @Override
    public String filterType() {
        return "pre";
    }

    //2.过滤器的执行顺序，越小越先执行
    @Override
    public int filterOrder() {
        return 0;
    }
    //3.代表是否执行该过滤器，true代表会执行，false代表不会执行该过滤器
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //4.具体执行的业务方法，该方法无论返回任何对象都会放行，包括null也会。只有设置指定的参数才不会放行(放行东西，将jwt所需要的请求头放到filter的请求头中并放行)
    @Override
    public Object run() throws ZuulException {
        //1.从过滤器的请求得到上下文对象
        RequestContext context = RequestContext.getCurrentContext();
        //2.得到请求对象
        HttpServletRequest request = context.getRequest();
        //2.1放行东西，因为当我们发送请求到网关时是两次请求，此方法（OPTIONS）需要放行
        if(request.getMethod().equals("OPTIONS")){
            return null;
        }
        //2.2一些登录的url放行
        if(request.getRequestURL().toString().contains("/login")){
            return null;
        }
        //3.得到请求头
        String authorization = request.getHeader("Authorization");
        //4.判断是否有值，有再判断是否为Bearer 开头，再得到token对象并解析，得到权限参数，判断权限
        if(StringUtils.isNotBlank(authorization)){
            //4.1 判断是否Bearer 开头
            if(authorization.startsWith("Bearer ")){
                //4.1.1 从第七位开始截取得到token
                String token = authorization.substring(7);
                //4.1.2 解析token
                Claims claims = jwtUtil.parseToken(token);
                //4.1.3 判断是否存在
                if(claims != null){
                    //4.1.3.1 得到权限
                    String roles = (String) claims.get("roles");
                    //4.1.3.2 判断是否存在并且是否为admin权限
                    if(StringUtils.isNotBlank(roles) && "admin".equals(roles)){
                        //4.1.3.3 将请求头对象放入过滤器请求头中，并放行
                        context.addZuulRequestHeader("Authorization",authorization);
                        return null;
                    }
                }
            }
        }
        //5.设置一系列拒绝访问的参数
        context.setSendZuulResponse(false);       //禁止向下响应内容
        context.setResponseStatusCode(403);         //设置响应的状态
        context.setResponseBody("拒绝访问！！！"); //返回响应的文本信息
        context.getResponse().setContentType("text/html;charset=utf-8");//设置响应的文本信息的字符编码
        return null;
    }
}
